package com.codi.bus.core.service.impl;

import com.codi.base.util.DateUtils;
import com.codi.base.util.MoneyUtils;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.dao.CdUserShareDao;
import com.codi.bus.core.dao.ProfitDao;
import com.codi.bus.core.dao.TradeOrdersDao;
import com.codi.bus.core.domain.CdUserShare;
import com.codi.bus.core.domain.Profit;
import com.codi.bus.core.domain.TradeOrders;
import com.codi.bus.core.resultModel.FundNetValueResult;
import com.codi.bus.core.resultModel.WorkingDayResult;
import com.codi.bus.core.service.FundDetailService;
import com.codi.bus.core.service.WorkingDateService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by asus on 2018/6/19.
 */
@Service
@Slf4j
public class ProfitRepairServiceImpl {
    @Autowired
    private ProfitDao profitDao;
    @Autowired
    private TradeOrdersDao tradeOrdersDao;
    @Autowired
    private CdUserShareDao cdUserShareDao;
    @Resource(name = "fundDetailService")
    private FundDetailService fundDetailService;
    @Autowired
    private WorkingDateService workingDateService;

    /**
     * 任务  2
     *
     *  dateOne 计算当日
     *  two  -1 计算当日前一日
     *  four  0 计算当日前0日
     * 把下面的插入数据 变成了 只能插当天有数据的
     * 准备再查一波  netValue 表   可以 多倒两天吧    如果 endDate 在 表里 没出现过   把那天的 数据  插进去
     *
     *
     */
    public void execProfit(String dateOne, int two, String dateThree, int four){
        //1
        List<CdUserShare> allList = cdUserShareDao.selectOneDayShare(dateOne);
        List<String> fundCodeList = Lists.newArrayList();
        for(CdUserShare share:allList){
            if ("161728".equals(share.getFundCode()) || "G20001".equals(share.getFundCode()) || "G20002".equals(share.getFundCode())) {
                continue;
            }
            if (!fundCodeList.contains(share.getFundCode())){

                fundCodeList.add(share.getFundCode());
            }
        }
        Date date = new Date();
        //2
        Date currentDate = DateUtils.addDay(date, two);
        List<FundNetValueResult> fundNetValueList = null;
        List<FundNetValueResult> fundNetValueListLast1 = null;
        List<FundNetValueResult> fundNetValueListLast2 = null;
        List<FundNetValueResult> lastFundNetValueList = null;
        Map<String, FundNetValueResult> netValues = new HashedMap();
        Map<String, FundNetValueResult> lastNetValues = new HashedMap();
        boolean gliDataException = false;
        try {
            fundNetValueList = fundDetailService.getFundNetValueByBatch(fundCodeList, currentDate);
            fundNetValueListLast2 = fundDetailService.getFundNetValueByBatch(fundCodeList, DateUtils.addDay(currentDate,-2));
            fundNetValueListLast1 = fundDetailService.getFundNetValueByBatch(fundCodeList, DateUtils.addDay(currentDate,-1));
            WorkingDayResult workingDayResult = workingDateService.getLastWorkingDay(currentDate);
            for (String fundCode : fundCodeList){
                log.debug("listFundCode:{}",fundCode);
            }
            lastFundNetValueList  = fundDetailService.getFundNetValueByBatch(fundCodeList, workingDayResult.getLastWorkingDay());

            for(FundNetValueResult result:fundNetValueList){
                netValues.put(result.getFundCode() + DateUtils.formatDate4(result.getTradingDay()) ,result);
            }
            for(FundNetValueResult result:fundNetValueListLast1){
                netValues.put(result.getFundCode() + DateUtils.formatDate4(result.getTradingDay()) ,result);
            }
            for(FundNetValueResult result:fundNetValueListLast2){
                netValues.put(result.getFundCode() + DateUtils.formatDate4(result.getTradingDay()) ,result);
            }
            for(FundNetValueResult result:lastFundNetValueList){
                lastNetValues.put(result.getFundCode(),result);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            gliDataException = true;
        }
        if (gliDataException || fundNetValueList == null) {
            log.error("================================从聚源获取基金净值信息错误");
        }

        Profit exitProfit = new Profit();

        String dateTime = DateUtils.getFormatedDate(DateUtils.addDay(currentDate,-3),"yyyy-MM-dd");
        String time = DateUtils.getFormatedDate(currentDate,"yyyy-MM-dd");
        //4
        String createTime = DateUtils.getFormatedDate(DateUtils.addDay(date,four),"yyyy-MM-dd HH:mm:ss");
        exitProfit.setDateTime(dateTime);

        List<Profit> exit = profitDao.selectProfit(exitProfit);
        Set<String> exitSet = Sets.newHashSet();
        for(Profit profit:exit){
            exitSet.add(profit.getUserId()+"-"+profit.getTradeAcco()+"-"+profit.getFundCode()+"-"+profit.getDateTime());
        }
        TradeOrders queryVo = new TradeOrders();

        String tempDate = DateUtils.getFormatedDate(DateUtils.addDay(currentDate, -15), "yyyyMMdd");
        queryVo.setCreateTime(tempDate);
        queryVo.setFundBusinCode(GlobalConstant.FUND_BUSIN_CODE_T0_FAST_APPLY_SELL);
        queryVo.setTaconfirmFlag(GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS);
        List<TradeOrders> tradeOrderCreateList = tradeOrdersDao.selectFastredeem(queryVo);
        //可以有多条 快赎
        Map<String, List<TradeOrders>> fastRedeemMap = Maps.newHashMap();
        for(TradeOrders orders:tradeOrderCreateList){
            if (fastRedeemMap.get(orders.getUserId()+"-"+orders.getFundCode()+"-"+orders.getTradeAcco()+"-"+orders.getApplyDate()) == null){
                List<TradeOrders> list = new ArrayList<>();
                fastRedeemMap.put(orders.getUserId()+"-"+orders.getFundCode()+"-"+orders.getTradeAcco()+"-"+orders.getApplyDate(),list);
                fastRedeemMap.get(orders.getUserId()+"-"+orders.getFundCode()+"-"+orders.getTradeAcco()+"-"+orders.getApplyDate()).add(orders);
            } else {
                fastRedeemMap.get(orders.getUserId()+"-"+orders.getFundCode()+"-"+orders.getTradeAcco()+"-"+orders.getApplyDate()).add(orders);
            }
        }
        for(CdUserShare share:allList){
            if ("161728".equals(share.getFundCode()) || "G20001".equals(share.getFundCode()) || "G20002".equals(share.getFundCode())) {
                continue;
            }
            Profit profit1 = Profit.builder()
                .userId(share.getUserId())
                .fundCode(share.getFundCode())
                .tradeAcco(share.getTradeAcco())
                .build();
            List<Profit> profitList = profitDao.selectNewCreateProfit(share.getUserId(), share.getClientId(), share.getTradeAcco(), share.getFundCode());

            BigDecimal accumulateProfit = new BigDecimal(0);
            if (!profitList.isEmpty()){
                accumulateProfit = profitList.get(0).getAccumulateProfitValue();
            }
            String type = share.getOfundType();
            String fundCode = share.getFundCode();
            String netKey = fundCode + getLastDateString(share,-1);
            log.debug("netKey:{}",netKey);
            FundNetValueResult valueResult = netValues.get(netKey);
            BigDecimal todayIncome;
            BigDecimal currentShare = share.getCurrentShare();
            if(currentShare == null){
                continue;
            }

            //要减去 这一天中 所有的快赎   节假日 要减去 节假日的所有快赎
            Date lastDay = DateUtils.addDay(DateUtils.stringToDate(share.getCreateTime().substring(0,8),"yyyyMMdd"),-1);
            WorkingDayResult workingDayResult = workingDateService.getLastWorkingDay(lastDay);
            Date lastWorkDay = workingDayResult.getLastWorkingDay();
            List<TradeOrders> tradeOrdersList = new ArrayList<>();
            //求求你看看 这时间类型 给我 整了多少麻烦
            for (int i = 1; i < 20; i++){
                if (DateUtils.addDay(lastDay,-i).equals(lastWorkDay)){
                    String k = share.getUserId()+"-"+share.getFundCode()+ "-"+share.getTradeAcco()+"-"+getLastDateString(share,-i);
                    List<TradeOrders> fastList = fastRedeemMap.get(k);
                    if (fastList != null){
                        tradeOrdersList.addAll(fastList);
                    }
                    break;
                }else {
                    List<TradeOrders> fastList = fastRedeemMap.get(share.getUserId()+"-"+share.getFundCode()+ "-"+share.getTradeAcco()+"-"+getLastDateString(share,-i));
                    if (fastList != null){
                        tradeOrdersList.addAll(fastList);
                    }
                }
            }
            if (!tradeOrdersList.isEmpty()){
                for (TradeOrders tradeOrders : tradeOrdersList){
                    if(tradeOrders != null && tradeOrders.getShares() != null && tradeOrders.getShares().doubleValue() > 0){
                        currentShare = currentShare.subtract(tradeOrders.getShares());
                    }
                }
            }

            Profit profit = new Profit();
            profit.setUserId(share.getUserId());
            profit.setClientId(share.getClientId());
            profit.setTradeAcco(share.getTradeAcco());
            profit.setFundCode(fundCode);
            String t = DateUtils.formatDate(DateUtils.addDay(DateUtils.stringToDate(share.getCreateTime().substring(0,8),"yyyyMMdd"),-1));
            profit.setDateTime(t);
            profit.setCreateTime(createTime);
            String key = profit.getUserId()+"-"+profit.getTradeAcco()+"-"+profit.getFundCode();
            String keyWithDate = profit.getUserId()+"-"+profit.getTradeAcco()+"-"+profit.getFundCode()+"-"+t;
            //货币
            if(GlobalConstant.FUND_TYPE_CURRENCY.equals(type)){

                if (valueResult == null || ! DateUtils.formatDate(valueResult.getTradingDay()).equals(t)) {
                    continue;
                }
                log.debug("基金1：{}，万分收益1：{}， 日期：{}，份额：{}",profit.getFundCode(),valueResult.getDailyProfit(),valueResult.getTradingDay(),currentShare);

                // 万份收益
                todayIncome = currentShare.divide(new BigDecimal(10000), 12,4).multiply(valueResult.getDailyProfit());
                profit.setNetValue(valueResult.getUnitNV());
                profit.setPreNetValue(valueResult.getUnitNV());
                profit.setShares(currentShare);
                profit.setProfitValue(todayIncome);

                if(accumulateProfit == null){
                    accumulateProfit = new BigDecimal("0");
                }
                profit.setAccumulateProfitValue(accumulateProfit.add(todayIncome));
                if(!exitSet.contains(keyWithDate)){
                    CdUserShare cdUserShare = CdUserShare.builder()
                        .userId(profit.getUserId())
                        .tradeAcco(profit.getTradeAcco())
                        .fundCode(profit.getFundCode())
                        .createTime(share.getCreateTime().substring(0,8))
                        .build();
                    cdUserShareDao.updateShare(cdUserShare);
                    profitDao.insert(profit);
                }
            }else {
                if(workingDateService.isWorkingDate(currentDate)){
                    // 获取上一工作日净值
                    FundNetValueResult fundNetValueResult = lastNetValues.get(fundCode);
                    if (fundNetValueResult == null) {
                        continue;
                    }
                    log.debug("fundCode:{}",fundCode);
                    log.debug("fundNetValueResult:{}",fundNetValueResult);
                    BigDecimal lastUnitValue = fundNetValueResult.getUnitNV();
                    log.debug("fundCode:{},now:{},last:{}",profit.getFundCode(),valueResult.getDailyProfit(),lastUnitValue);
                    BigDecimal margin = MoneyUtils.subtract(valueResult.getUnitNV(), lastUnitValue);
                    todayIncome = currentShare.multiply(margin);
                    profit.setNetValue(valueResult.getUnitNV());
                    profit.setPreNetValue(lastUnitValue);
                    profit.setShares(currentShare);
                    profit.setProfitValue(todayIncome);
                    if(accumulateProfit == null){
                        accumulateProfit = new BigDecimal("0");
                    }
                    profit.setAccumulateProfitValue(accumulateProfit.add(todayIncome));
                    if(!exitSet.contains(keyWithDate)){
                        CdUserShare cdUserShare = CdUserShare.builder()
                            .userId(profit.getUserId())
                            .tradeAcco(profit.getTradeAcco())
                            .fundCode(profit.getFundCode())
                            .createTime(share.getCreateTime().substring(0,8))
                            .build();
                        cdUserShareDao.updateShare(cdUserShare);
                        profitDao.insert(profit);
                    }
                }
            }
        }
    }

    //把 yyyyMMdd  转化成 时间  再  减一天 再变回来  @曾祥亮
    private String getLastDateString(CdUserShare share, int i){
        return DateUtils.formatDate4(DateUtils.addDay(DateUtils.stringToDate(share.getCreateTime().substring(0,8),"yyyyMMdd"),i));
    }
}
